package gui;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.road0329.tools.proto_parse_tool.chargingpile.BaseFrame;
import org.road0329.tools.proto_parse_tool.chargingpile.MsgDcsResult;
import org.road0329.tools.proto_parse_tool.chargingpile.ProtocolJuhuaHandle;
import org.road0329.tools.proto_parse_tool.component.Dictionary;
import org.road0329.tools.proto_parse_tool.ems.*;
import org.road0329.tools.proto_parse_tool.ems.dataobject.CdIotUpData;
import org.road0329.tools.proto_parse_tool.ems.dataobject.DyIotUpData;
import org.road0329.tools.proto_parse_tool.ems.qgdw3761.ProtocolGW09Handle;
import org.road0329.tools.proto_parse_tool.ems.xintian.ProtocolXinTianHandle;
import org.road0329.tools.proto_parse_tool.utils.ProtocolUtils;
import org.road0329.tools.proto_parse_tool.utils.StringUtil;
import de.felixroske.jfxsupport.FXMLController;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.stage.Modality;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;

@FXMLController
public class MainWindowController {

    @FXML
    private RadioMenuItem charingPileProtocolItem;

    @FXML
    private MenuItem aboutItem;

    @FXML
    private MenuItem parseMessageItem;

    @FXML
    private MenuItem exitItem;

    @FXML
    private MenuItem clearMessageItem;

    @FXML
    private TextArea srcMessageText;

    @FXML
    private TextArea destMessageText;

    @FXML
    private TreeTableView destMessageTable;

    @FXML
    private RadioMenuItem cjt188ProtocolItem;

    @FXML
    private RadioMenuItem qgdw3761ProtocolItem;

    @FXML
    private RadioMenuItem dlt64507ProtocolItem;

    @FXML
    private RadioMenuItem dyIotProtocolItem;

    @FXML
    private RadioMenuItem cdIotProtocolItem;

    @FXML
    private RadioMenuItem waterCollectorProtocolItem;
    @FXML
    private RadioMenuItem xintianWaterProtocolItem;

    @FXML
    private ToggleGroup ProtocolGroup;

    @FXML
    void parseMessage(ActionEvent event) {
        String content = srcMessageText.getText();
        if (StringUtil.isEmpty(content)) {
            destMessageText.setText("要解析的报文不能为空");
            return;
        }
        try {
            if(charingPileProtocolItem.isSelected()) {
                destMessageText.setText(parseChargingPileProtocol(content));
            } else if(cjt188ProtocolItem.isSelected()) {
                destMessageText.setText(parseCjt188Protocol(content));
            } else if(qgdw3761ProtocolItem.isSelected()) {
                destMessageText.setText(parseQgdw3761Protocol(content));
            } else if(dlt64507ProtocolItem.isSelected()) {
                destMessageText.setText(parseDlt64507Protocol(content));
            }else if(dyIotProtocolItem.isSelected()) {
                destMessageText.setText(parseDyIotProtocol(content));
            }else if(cdIotProtocolItem.isSelected()) {
                destMessageText.setText(parseCdIotProtocol(content));
            }else if(waterCollectorProtocolItem.isSelected()) {
                destMessageText.setText(parseWaterCollectorProtocol(content));
            }else if(xintianWaterProtocolItem.isSelected()) {
                destMessageText.setText(parseXintianWaterProtocol(content));
            }
            String json = destMessageText.getText();
            json = replaceWithDictionary(json);
            showJsonTable(json);
        } catch (Exception e) {
            destMessageText.setText(errInfo(e));
        }

    }

    public String replaceWithDictionary(String input) {
        if(Dictionary.DICT.isEmpty()) {
            Dictionary.init();
        }
        for (Map.Entry<String, String> entry : Dictionary.DICT.entrySet()) {
            input = input.replace( entry.getKey(), entry.getValue());
        }
        return input;
    }

    private void showJsonTable(String json) {
        // 解析JSON字符串
        JSONObject jsonObject = JSON.parseObject(json);

        // 创建根节点
        TreeItem<JSONProperty> rootItem = new TreeItem<>(new JSONProperty("设备上报", ""));

        // 构建JSON树形表格
        buildJSONTreeTable(jsonObject, rootItem);

        // 创建树形表格列
        TreeTableColumn<JSONProperty, String> keyColumn = new TreeTableColumn<>("键");
        keyColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<JSONProperty, String> p) ->
                new SimpleStringProperty(p.getValue().getValue().getKey()));
        keyColumn.setPrefWidth(300);

        TreeTableColumn<JSONProperty, String> valueColumn = new TreeTableColumn<>("值");
        valueColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<JSONProperty, String> p) ->
                new SimpleStringProperty(p.getValue().getValue().getValue()));

        // 设置根节点展开属性
        rootItem.setExpanded(true);
        expandAllNodes(rootItem);
        destMessageTable.setRoot(rootItem);

        // 将列设置到树形表格
        destMessageTable.getColumns().clear();
        destMessageTable.getColumns().addAll(keyColumn, valueColumn);
        destMessageTable.refresh();

    }

    private void expandAllNodes(TreeItem<JSONProperty> parentItem) {
        // 设置当前节点展开
        parentItem.setExpanded(true);
        // 遍历子节点并递归展开
        for (TreeItem<JSONProperty> childItem : parentItem.getChildren()) {
            expandAllNodes(childItem);
        }
    }

    private void buildJSONTreeTable(JSONObject jsonObject, TreeItem<JSONProperty> parentItem) {
        for (String key : jsonObject.keySet()) {
            Object value = jsonObject.get(key);
            JSONProperty property = new JSONProperty(key, value.toString());
            TreeItem<JSONProperty> item = new TreeItem<>(property);
            parentItem.getChildren().add(item);

            if (value instanceof JSONObject) {
                // 处理JSON对象的情况
                buildJSONTreeTable((JSONObject) value, item);
            } else if (value instanceof JSONArray) {
                // 处理JSON数组的情况
                JSONArray jsonArray = (JSONArray) value;
                for (int i = 0; i < jsonArray.size(); i++) {
                    Object arrayValue = jsonArray.get(i);
                    JSONProperty arrayProperty = new JSONProperty("[" + i + "]", arrayValue.toString());
                    TreeItem<JSONProperty> arrayItem = new TreeItem<>(arrayProperty);
                    item.getChildren().add(arrayItem);

                    if (arrayValue instanceof JSONObject) {
                        buildJSONTreeTable((JSONObject) arrayValue, arrayItem);
                    }
                }
            }
        }
    }

    public static String errInfo(Exception e) {
        StringWriter sw = null;
        PrintWriter pw = null;
        try {
            sw = new StringWriter();
            pw = new PrintWriter(sw);
            // 将出错的栈信息输出到printWriter中
            e.printStackTrace(pw);
            pw.flush();
            sw.flush();
            return sw.toString();
        } finally {
            if (sw != null) {
                try {
                    sw.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (pw != null) {
                pw.close();
            }
        }
    }

    private String parseChargingPileProtocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        BaseFrame frame = ProtocolJuhuaHandle.validateMessage(buf);
        if (frame == null) {
            throw new Exception("报文格式有误");
        }
        MsgDcsResult result = ProtocolJuhuaHandle.decoder(frame);
        return JSON.toJSONString(result, true);
    }

    private String parseCjt188Protocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        PointCommInfo pointCommInfo = Protocol188Util.parseCommand(buf);
        if (pointCommInfo == null) {
            throw new Exception("报文格式有误");
        }
        return JSON.toJSONString(pointCommInfo, true);
    }

    private String parseQgdw3761Protocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        MsgDcsResult result = ProtocolGW09Handle.decoder(buf);
        if (result == null) {
            throw new Exception("报文格式有误");
        }
        return JSON.toJSONString(result, true);
    }

    private String parseDlt64507Protocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        PointCommInfo pointCommInfo = Protocol645_07Util.parseCommand(buf);
        if (pointCommInfo == null) {
            throw new Exception("报文格式有误");
        }
        return JSON.toJSONString(pointCommInfo, true);
    }

    private String parseDyIotProtocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        DyIotUpData dyIotUpData = ProtocolDyIotWaterUtil.parseMessage(buf);
        if (dyIotUpData == null) {
            throw new Exception("报文格式有误");
        }
        return JSON.toJSONString(dyIotUpData, true);
    }

    private String parseCdIotProtocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        CdIotUpData cdIotUpData = ProtocolCdIotWaterUtil.parseMessage(buf);
        if (cdIotUpData == null) {
            throw new Exception("报文格式有误");
        }
        return JSON.toJSONString(cdIotUpData, true);
    }

    private String parseWaterCollectorProtocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        Object result = ProtocolWaterMeterCollectorUtil.parseMessage(buf);
        if (result == null) {
            throw new Exception("报文格式有误");
        }
        return JSON.toJSONString(result, true);
    }

    private String parseXintianWaterProtocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        Object result = ProtocolXinTianHandle.decoder(buf);
        if (result == null) {
            throw new Exception("报文格式有误");
        }
        return JSON.toJSONString(result, true);
    }

    @FXML
    void clearMessage(ActionEvent event) {
        srcMessageText.setText("");
        destMessageText.setText("");
    }

    @FXML
    void exit(ActionEvent event) {
        System.exit(0);
    }

    @FXML
    void about(ActionEvent event) throws IOException {
        Main.showView(AboutDialogView.class, Modality.NONE);
    }

    public static class JSONProperty {
        private final SimpleStringProperty key;
        private final SimpleStringProperty value;
        public JSONProperty(String key, String value) {
            this.key = new SimpleStringProperty(key);
            this.value = new SimpleStringProperty(value);
        }

        public String getKey() {
            return key.get();
        }

        public SimpleStringProperty keyProperty() {
            return key;
        }

        public String getValue() {
            return value.get();
        }

        public SimpleStringProperty valueProperty() {
            return value;
        }
    }
}

